import base64
import os
import string
import time
import traceback
import uuid
from datetime import datetime
from functools import reduce
from io import BytesIO

import requests

from app import app


def safe_commit(db):
    try:
        db.session.commit()
        return True
    except:
        db.session.rollback()
        print("数据库提交异常：", traceback.format_exc())
        return False


def get_today_timestamp():
    """
    获取今天凌晨的时间戳
    """
    now = datetime.now().date()
    now_time_stamps = time.mktime(now.timetuple())
    return int(now_time_stamps)


def get_today_range():
    """
    获取今天一整天的时间范围0：0~23：59：59
    """
    today_start = get_today_timestamp()
    today_range = (today_start, today_start + 24 * 60 * 60 - 1)  # 今天一整天的时间戳范围
    return today_range


def tms_to_time_str(timestamp, fmt='%Y-%m-%d'):
    """
    时间戳转日期字符串
    """
    return datetime.fromtimestamp(timestamp).strftime(fmt)


def str_to_timestamp(strftime):
    """
    日期字符串转时间戳
    """
    time_array = time.strptime(strftime, "%Y-%m-%d")
    return int(time.mktime(time_array))


def get_zero_time(timestamp):
    """
    根据时间戳，返回那一天凌晨的时间戳
    """
    s = tms_to_time_str(timestamp)
    return str_to_timestamp(s)


def get_zero_time_range(start_time, end_time):
    """
    根据开始时间和结束时间返回期间每天的凌晨时间戳
    :param start_time:
    :param end_time:
    :return: list
    """
    start_time = get_zero_time(start_time)
    end_time = get_zero_time(end_time)
    result = []
    while start_time <= end_time:
        result.append(start_time)
        start_time += 86400
    return result


def img_b64_to_bytes(str_b64):
    """
    带文件类型的b64字符串转成bytes
    """
    head, body = str_b64.split(',')
    fmt = head.split('/')[1].split(';')[0]
    return fmt, base64.b64decode(body)


def get_sex_from_card_id(card_id):
    """
    通过用户证件号码获取性别
    :param card_id: 身份证号码
    :return: 性别(male female)
    """
    # if not str(card_id).isdigit():
    #     return None
    sex_pos = card_id[-2]
    return 'female' if not int(sex_pos) % 2 else 'male'


def verify_id_card(ids: str,
                   li: list = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2],
                   ver_list: list = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2]) -> bool:
    """
    验证用户身份证号是否有效
    :param ids:用户的身份证号码
    :param li:乘积系数列表
    :param ver_list:验证字符列表
    :return: 是否有效
    """
    if not isinstance(ids, (list, str)) or len(ids) != 18:  #
        return False
    ids = ids.upper()
    # 按照身份证的验证的乘积系数求和
    last_index = reduce(lambda x, y: li[y] * int(ids[y]) + x, range(0, 17), 0) % 11
    # 对比验证位字符是否正确
    return str(ver_list[last_index]).upper() == ids[17]


def get_xy_by_ip(ip):
    """
    根据ip地址获取经纬度
    :param ip:
    """
    url = "https://api.map.baidu.com/location/ip?ak=HQi0eHpVOLlRuIFlsTZNGlYvqLO56un3&coor=bd09ll&ip={}".format(ip)
    response = requests.post(url)
    if response.status_code != 200:
        return None
    data = response.json()
    if 'point' not in data:
        return None
    return data['point']


def write_log(content):
    """
    临时使用的写日志
    """
    try:
        content = str(content)
        now = datetime.now()
        log_path = app.config.get('LOG_PATH', '/data/htdocs/bks_sports/log/runline')
        if not os.path.exists(log_path):
            os.makedirs(log_path)
        log_name = str(now.year) + str(now.month) + str(now.day) + '.log'
        log_file_path = os.path.join(log_path, log_name)
        with open(log_file_path, 'a', encoding='utf8') as file:
            s = '[' + str(now) + '] ' + content + '\n'
            file.write(s)
    except:
        traceback.print_exc()


def check_safe_str(s):
    """
    判断s是不是只含有字母数字下划线和英文的句点
    :param s:
    :return:
    """
    safe_char_set = set(string.ascii_letters + string.digits)
    safe_char_set.add('_')
    safe_char_set.add('.')
    check_char_set = set(s)
    result = check_char_set - safe_char_set
    return not bool(len(result))


def check_safe_nickname(s):
    """
    判断s是不是只含有中文、字母、数字、下划线和英文句点
    :param s:
    :return:
    """
    safe_char_set = set(string.ascii_letters + string.digits)
    safe_char_set.add('_')
    safe_char_set.add('.')
    check_char_set = set(s)
    result = check_char_set - safe_char_set
    if len(result) == 0:
        return True
    for char in result:
        if not u'\u4e00' <= char <= u'\u9fff':
            return False
    return True


if __name__ == '__main__':
    # print(get_zero_time_range(1596250308, 1596250308))
    print(check_safe_str("abcdAcd.0~中文"))
    print(check_safe_nickname("abcdAcd.0中文"))
